feat(stdlib): add fs_*/env_args/format builtins + my-cli argv forwarding#2
Merged
Merged
Conversation
Six new stdlib builtins for tooling workloads:
- fs_write_file / fs_read_file / fs_create_dir_all / fs_exists
- env_args (host-supplied with std::env::args().skip(1) fallback)
- format (positional {} substitution, {{ }} escapes)
Plus PROGRAM_ARGS OnceLock + pub fn set_program_args, and my-cli's Run
subcommand grows a trailing_var_arg field forwarded to set_program_args.
Validated by an end-to-end run of an out-of-tree scaffold tool against
six idaptik-port component repos.
See PR body for details and open design questions.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4 tasks
hyperpolymath
added a commit
that referenced
this pull request
May 1, 2026
Two more CI infra fixes uncovered while sorting PR #2: * hypatia-scan.yml: setup-beam@v1.18.2 doesn't recognise ImageOS ubuntu24, so every Hypatia run aborts with "Tried to map a target OS from env. variable 'ImageOS' (got ubuntu24), but failed." Bumped to v1.24.0 (8d44588995...), which lists ubuntu-24.04 support in its README. * workflow-linter.yml: the SHA-pinned-actions check ran `grep -rn "uses:" .github/workflows/`, which matches the linter's own explanatory comment `# Find any uses: lines that don't have @sha format`. The comment is then flagged as unpinned and the check fails on itself. Anchor the regex on leading-whitespace + the directive form `^[[:space:]]+uses:[[:space:]]` so comments no longer match.
hyperpolymath
added a commit
that referenced
this pull request
May 2, 2026
…p-beam ubuntu24, workflow-linter self-match) (#3) * ci(hypatia): fix unresolvable upload-artifact SHA pin The pinned SHA 65c79d7f54e76e4e3c7a8f34db0f4ac8b515c478 doesn't exist in actions/upload-artifact, so the runner errors with "Unable to resolve action ... unable to find version" and Hypatia scans never start. Pinned to v4.6.2 (ea165f8d65b6e75b540449e92b4886f43607fa02), which is the latest v4 series matching the original `# v4` comment. * ci: bump setup-beam to v1.24.0; tighten workflow-linter uses: regex Two more CI infra fixes uncovered while sorting PR #2: * hypatia-scan.yml: setup-beam@v1.18.2 doesn't recognise ImageOS ubuntu24, so every Hypatia run aborts with "Tried to map a target OS from env. variable 'ImageOS' (got ubuntu24), but failed." Bumped to v1.24.0 (8d44588995...), which lists ubuntu-24.04 support in its README. * workflow-linter.yml: the SHA-pinned-actions check ran `grep -rn "uses:" .github/workflows/`, which matches the linter's own explanatory comment `# Find any uses: lines that don't have @sha format`. The comment is then flagged as unpinned and the check fails on itself. Anchor the regex on leading-whitespace + the directive form `^[[:space:]]+uses:[[:space:]]` so comments no longer match. * ci(hypatia): cd into $HOME/hypatia in shell instead of via working-directory \${{ env.HOME }} resolves the workflow's `env:` block, not the runner's $HOME, so the previous `working-directory: \${{ env.HOME }}/hypatia` expanded to /hypatia and the build step failed with "working directory '/hypatia'. No such file or directory". Use a shell `cd "$HOME/hypatia"` instead, matching how the Clone and Run steps already address the path.
hyperpolymath
added a commit
that referenced
this pull request
May 4, 2026
* ci(hypatia): fix unresolvable upload-artifact SHA pin The pinned SHA 65c79d7f54e76e4e3c7a8f34db0f4ac8b515c478 doesn't exist in actions/upload-artifact, so the runner errors with "Unable to resolve action ... unable to find version" and Hypatia scans never start. Pinned to v4.6.2 (ea165f8d65b6e75b540449e92b4886f43607fa02), which is the latest v4 series matching the original `# v4` comment. * ci: bump setup-beam to v1.24.0; tighten workflow-linter uses: regex Two more CI infra fixes uncovered while sorting PR #2: * hypatia-scan.yml: setup-beam@v1.18.2 doesn't recognise ImageOS ubuntu24, so every Hypatia run aborts with "Tried to map a target OS from env. variable 'ImageOS' (got ubuntu24), but failed." Bumped to v1.24.0 (8d44588995...), which lists ubuntu-24.04 support in its README. * workflow-linter.yml: the SHA-pinned-actions check ran `grep -rn "uses:" .github/workflows/`, which matches the linter's own explanatory comment `# Find any uses: lines that don't have @sha format`. The comment is then flagged as unpinned and the check fails on itself. Anchor the regex on leading-whitespace + the directive form `^[[:space:]]+uses:[[:space:]]` so comments no longer match. * ci(hypatia): cd into $HOME/hypatia in shell instead of via working-directory \${{ env.HOME }} resolves the workflow's `env:` block, not the runner's $HOME, so the previous `working-directory: \${{ env.HOME }}/hypatia` expanded to /hypatia and the build step failed with "working directory '/hypatia'. No such file or directory". Use a shell `cd "$HOME/hypatia"` instead, matching how the Clone and Run steps already address the path.
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds six new stdlib builtins to enable My (Solo dialect) for tooling workloads — file I/O, CLI argv, and string formatting — and a small my-cli extension to forward trailing argv to the program.
Motivation
Pre-this-PR, Solo's runtime stdlib was rich for in-memory + terminal-I/O code (71 builtins) but explicitly not tooling-class —
IMPLEMENTATION.mdlistsstd::fs,std::io,std::collections::mapetc. as Phase-2 roadmap items. That meant scaffold tools / code generators / audit utilities couldn't be written in My; they had to fall back to Python.This PR ships the smallest set of additions that lets a real Solo tooling program be written end-to-end. Validated by an out-of-tree scaffold/audit tool (
scaffold-component.myfor theidaptik-portpolyrepo work) running clean against six component repos.What's added
crates/my-lang/src/stdlib.rsfs_write_file(path: String, content: String) -> Unitfs_read_file(path: String) -> Stringfs_create_dir_all(path: String) -> Unitfs_exists(path: String) -> Boolenv_args() -> [String]std::env::args().skip(1)format(template: String, args: [Any]) -> String{}substitution;{{and}}escapePlus a static
PROGRAM_ARGS: OnceLock<Vec<String>>andpub fn set_program_args(args: Vec<String>)so embedders can supply argv to programs without my-cli's clap consuming flags.All six are stateless
fn(Vec<Value>) -> Result<Value, RuntimeError>pointers consistent with existing builtins. Errors route throughRuntimeError::Custom(String)for I/O failures;RuntimeError::TypeErrorfor type mismatches.crates/my-cli/src/main.rsRunsubcommand grows aargs: Vec<String>field withtrailing_var_arg = true, allow_hyphen_values = true, so:forwards
--audit /path/to/repotoenv_args()rather than clap rejecting--audit. The match arm callsmy_lang::stdlib::set_program_args(args)before invoking the interpreter.Test plan
cargo build --release --bin my -p my-cliclean (3 pre-existing dead-code warnings unchanged)/tmp/smoke.my):scaffold-audit.my) against six idaptik-port component repos — all sixOKaudits, exit 0.crates/my-lang/tests/for each new builtin (success + error paths). Not added in this PR; happy to follow up.Open design questions
fs_write_fileauto-creates parent dirs;fs_create_dir_allis exported separately because some scaffolds want explicit empty dirs. Acceptable, or split write into two funcs?RuntimeError::Custom(String). A newRuntimeError::IoError { path, kind, message }variant would be cleaner long-term but would touch every error-handling path; deferred.formatplaceholder syntax. Positional{}only. No{name}named placeholders, no{0}/{1}indexed. Aligned with Rust'sformat!minimum surface; can extend later.env_argssemantics. Falls back tostd::env::args().skip(1)whenset_program_argshasn't been called. Skipping arg[0] matches typical CLI ergonomics but could be debated.Related
str_concat/formatchains) — discovered during the validation tooling work; not in scope for this PR but worth knowing about.Why merge this
Six builtins, ~290 LOC of Rust, no breaking changes. Unblocks the entire tooling category; concretely unblocks the idaptik-port polyrepo scaffolding pipeline that produced this work.
🤖 Generated with Claude Code